
E.Config.get("SelectionSupport").selectOnHover = false;
E.Config.get("SelectionSupport").plainCursorKeys = false;
// Factors to consider horizontal and vertical distances for visual moves
E.Config.get("SelectionSupport").hFactor = 0.1;
E.Config.get("SelectionSupport").vFactor = 1;

E.SelectionSupport = function(doc, initialEntityView) {
  E.SelectionSupport._super.call(this);
  this.doc = doc;
	this.doc.selectionSupport = this;
	E.Config.apply(this, "SelectionSupport");
  var d = this.doc.doc;
  this.initialEntityView = initialEntityView;
  if (!this.initialEntityView)
    this.initialEntityView = EntityView.getFirstChildEntityView(d.body);
  new EventListener(d, "dblclick", function(evn) {
  	if (this.current && this.current.perform())
			return EventListener.cancelEvent(evn);
  }, this);
  new EventListener(d, "click", this.handleMouseEvent, this);
  if (this.selectOnHover)
    new EventListener(d, "mouseover", this.handleMouseEvent, this);
  new EventListener(d, "contextmenu", this.handleMouseEvent, this);
  new EventListener(d, "keydown", this.handleKeyEvent, this);
}
Object.extend("E.SelectionSupport", "E.Base");

E.SelectionSupport.prototype.activate = function(active, scrollIntoView) {
	if (this.current) {
	  this.current.activate(active, scrollIntoView);
	}
	else if (active) {
		var ev = EntityView.getVisualTopCenter();
		if (!ev)
		  ev = this.initialEntityView;
	  this.select(ev, scrollIntoView);
	}
}

E.SelectionSupport.prototype.process = function() {
	if (!this.current)
	  return;
	this.current.process();
	this.dispatchEvent( { type: "process", selection: this.current } );
}

E.SelectionSupport.prototype.isSelectable = function(dom) {
	return true;
}

E.SelectionSupport.prototype.handleMouseEvent = function(evn) {
	if (this.doc.locked)
	  return;
	if (evn._e_selectionHandled)
	  return;
	evn._e_selectionHandled = true;
  if (evn.ctrlKey) {
  	if (evn.target.href) {
  		this.doc.doc.location = evn.target.href;
      return EventListener.cancelEvent(evn);
  	}
    return;
  }
  var rightClick = (evn.button > 1) || (evn.type == "contextmenu");
	var targetDom = Dom(evn.target);
  if (!this.isSelectable(targetDom))
    return;
  var evElement = EntityView.getEntityViewElement(evn.target);
  if (!evElement)
    return;
  var newSel = this.select(Dom(evElement).getEntityView());
	if (!newSel && !this.current)
	  return;
  if (targetDom.isTextEdit())
    return;
	if (rightClick && this.current && this.onContextMenu)
	  this.onContextMenu(evn);
  return EventListener.cancelEvent(evn);
};

E.SelectionSupport.prototype.handleKeyEvent = function(evn) {
	if (this.doc.locked)
	  return;
	if (evn._e_selectionHandled)
	  return;
	evn._e_selectionHandled = true;
	if (Dom(evn.target).isTextEdit())
	  return;
  if ((evn.keyCode == 77) || (evn.keyCode == 93)) { // M or Windows Properties Key (context menu key)
  	if (!Dom(evn.target).isTextEdit() && this.current && this.onContextMenu)
  	  this.onContextMenu(evn);
  	else
  	  return;
  }
  else if (evn.keyCode == 13) { // Enter
  	if (!Dom(evn.target).isTextEdit() && this.current)
      this.current.perform();
  	else
  	  return;
  }
  else if (evn.ctrlKey && evn.shiftKey) {
  	if (!this.current && (evn.keyCode > 36) && (evn.keyCode < 41))
  	  this.select(this.initialEntityView);
    else if (evn.keyCode == 40) // arrow down
      this.select(this.current.entityView.getNextSibling(), true);
    else if (evn.keyCode == 39) // arrow right
      this.select(this.current.entityView.getFirstChild(), true);
    else if (evn.keyCode == 38) // arrow up
      this.select(this.current.entityView.getPreviousSibling(), true);
    else if (evn.keyCode == 37) // arrow left
      this.select(this.current.entityView.getParent(), true);
    else
      return;
  }
  else if (evn.ctrlKey || this.plainCursorKeys) {
  	if (!this.current && (evn.keyCode > 36) && (evn.keyCode < 41))
  	  this.select(this.initialEntityView);
    else if (evn.keyCode == 40) // arrow down
      this.select(this.current.entityView.getDown(null, this.hFactor), true);
    else if (evn.keyCode == 39) // arrow right
      this.select(this.current.entityView.getRight(null, this.hFactor), true);
    else if (evn.keyCode == 38) // arrow up
      this.select(this.current.entityView.getUp(null, this.vFactor), true);
    else if (evn.keyCode == 37) // arrow left
      this.select(this.current.entityView.getLeft(null, this.vFactor), true);
    else
      return;
  }
  else
    return;
  return EventListener.cancelEvent(evn);
}

E.SelectionSupport.prototype.select = function(entityView, scrollIntoView) {
  if (!entityView)
    return null;
  if (!this.isSelectable(entityView.dom))
    return null;
  if (this.current) {
  	if (this.current.entityView == entityView) {
  		this.current.activate(true);
  	  return null;
  	}
  	if (!this.current.activate(false))
  	  return null;
  }
  this.current = this.createSelection(entityView);
  this.current.activate(true, scrollIntoView);
  return this.current;
}

E.SelectionSupport.prototype.unselect = function() {
  if (!this.current)
    return null;
 	this.current.activate(false);
 	this.current = null;
}

E.SelectionSupport.prototype.createSelection = function(entityView) {
  return new E.Selection(entityView);
}

E.SelectionSupport.prototype.onTabKey = function(evn) {
}

E.SelectionSupport.prototype.onCancel = function(evn) {
  this.current && this.current.activate(false);
}


E.Selection = function(entityView) {
  this.entityView = entityView;
  this.active = false;
}

E.Selection.prototype.contains = function(node) {
  while (node != null) {
    if (this.entityView.contains(node))
      return true;
    node = node.parentNode;
  }
  return false;
}

E.Selection.prototype.addPanelToHide = function(panel) {
	if (!this._panelsToHide)
	  this._panelsToHide = new Array();
	this._panelsToHide[this._panelsToHide.length] = panel;
}

E.Selection.prototype.activate = function(active, scrollIntoView) {
  this.active = active;
  if (this._panelsToHide) {
  	for (var i = 0; i < this._panelsToHide.length; ++i)
  	  this._panelsToHide[i].hide();
  	this._panelsToHide = null;
  }
}

E.Selection.prototype.process = function() {
  this.entityView.markInProcess(true);
}

E.Selection.prototype.perform = function() {
  alert("Perform selection " + this);
  return true;
}


